﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ModelResourceManager.UserModel;

namespace ModelResourceManager.QueueModel
{
    public class QueueManager
    {
        private readonly EntityQueueManager _entityQueueManager;

        public QueueManager()
        {
            _entityQueueManager = new EntityQueueManager();
        }

        public bool Add(QueueDTO queueDTO)
        {
            if (queueDTO == null)
                return false;
            Queue queue = ParseToQueue(queueDTO);
            if (queue == null)
                return false;
            bool result = _entityQueueManager.Add(queue);
            return result;
        }

        public bool Update(QueueDTO queueDTO)
        {
            if (queueDTO == null)
                return false;
            Queue queue = ParseToQueue(queueDTO);
            if (queue == null)
                return false;
            bool result = _entityQueueManager.Update(queue);
            return result;
        }

        public bool Delete(Guid id)
        {
            if (id == Guid.Empty)
                return false;
            bool result = _entityQueueManager.Delete(id);
            return result;
        }

        public QueueDTO GetCurrentQueue(Guid id)
        {
            if (id == Guid.Empty)
                return null;
            Queue queue = _entityQueueManager.GetCurrentQueue(id);
            if (queue == null)
                return null;
            QueueDTO queueDTO = ParseToQueueDTO(queue);
            return queueDTO;
        }

        public List<QueueDTO> GetAll()
        {
            List<Queue> queues = _entityQueueManager.GetAll();
            if (queues == null)
                return null;
            List<QueueDTO> queueDTOs = queues.Select(ParseToQueueDTO).ToList();
            return queueDTOs;
        }

        public List<QueueDTO> GetAllForUser(Guid userId)
        {
            IEnumerable<Queue> queues = _entityQueueManager.GetAllForUser(userId);
            if (queues == null)
                return null;
            return queues.Select(ParseToQueueDTO).ToList();
        }

        public List<QueueDTO> GetAllForResource(Guid resourceId)
        {
            IEnumerable<Queue> queues = _entityQueueManager.GetAllForUser(resourceId);
            if (queues == null)
                return null;
            return queues.Select(ParseToQueueDTO).ToList();
        }

        public List<string[]> CheckAvaiable(QueueDTO queueDTO)
        {
            if (queueDTO == null)
                return null;
            Queue queue = ParseToQueue(queueDTO);
            if (queue == null)
                return null;
            return CreateResultString(GetIntersectQueues(queue, _entityQueueManager.GetAllForUser(queue.UserId)),
                                      GetIntersectQueues(queue, _entityQueueManager.GetAllForResource(queue.ResourceId)));
        }

        private IEnumerable<Queue> GetIntersectQueues(Queue newQueue, IEnumerable<Queue> queues)
        {
            return queues.Where(queue =>
                (queue.StartTime <= newQueue.StartTime &&
                    queue.FinishTime >= newQueue.StartTime) ||
                (queue.StartTime <= newQueue.FinishTime &&
                    queue.FinishTime >= newQueue.FinishTime));
        }

        private List<string[]> CreateResultString(IEnumerable<Queue> intersectUserQueues,
            IEnumerable<Queue> intersectResourceQueues)
        {
            var resultString = new List<string[]>();

            if (intersectUserQueues.Any())
            {
                resultString.Add(new[] { "Warning! You already in line on:" });

                resultString.AddRange(intersectUserQueues.Select(intersectUserQueue =>
                    new[] 
                                {
                                    new ResourceModel.ResourceManager().GetResourceName(intersectUserQueue.ResourceId), 
                                    "between", 
                                    intersectUserQueue.StartTime.ToShortTimeString(),
                                    "and", 
                                    intersectUserQueue.FinishTime.ToShortTimeString()
                                }));
            }

            else if (intersectResourceQueues.Any())
            {
                resultString.Add(new[] { "Error", "This resource is already busy" });

                resultString.AddRange(intersectResourceQueues.Select(intersectResourceQueue =>
                    new[]
                                {
                                    "by",
                                    new UserManager().GetCurrentUser(intersectResourceQueue.UserId).Login,
                                    "between", 
                                    intersectResourceQueue.StartTime.ToShortTimeString(),
                                    "and",
                                    intersectResourceQueue.FinishTime.ToShortTimeString()
                                }));
            }

            else
            {
                resultString.Add(new[] { "Available" });
            }
            return resultString;
        }

        private Queue ParseToQueue(QueueDTO queueDTO)
        {
            return new Queue()
            {
                QueueId = queueDTO.QueueId,
                ResourceId = queueDTO.ResourceId,
                UserId = queueDTO.UserId,
                StartTime = queueDTO.StartTime,
                FinishTime = queueDTO.FinishTime,
                MessageTime = queueDTO.MessageTime
            };
        }

        private QueueDTO ParseToQueueDTO(Queue queue)
        {
            return new QueueDTO()
            {
                QueueId = queue.QueueId,
                ResourceId = queue.ResourceId,
                UserId = queue.UserId,
                StartTime = queue.StartTime,
                FinishTime = queue.FinishTime,
                MessageTime = queue.MessageTime
            };
        }
    }
}
